package cs236369.hw5.rest;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Collection;
import java.util.GregorianCalendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.log4j.Logger;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;

import cs236369.hw5.db.DbHandler;
import cs236369.hw5.db.DbHandlerImp;
import cs236369.hw5.db.beans.DbEvent;
import cs236369.hw5.db.beans.DbMessage;
import cs236369.hw5.db.types.DbMsgType;
import cs236369.hw5.util.ResourceLoader;
import cs236369.hw5.xml.XmlUtils;
import cs236369.hw5.xml.jaxb.CrowdSourcing;
import cs236369.hw5.xml.jaxb.Event;
import cs236369.hw5.xml.jaxb.Location;
import cs236369.hw5.xml.jaxb.Message;
import cs236369.hw5.xml.jaxb.MessageType;
import cs236369.hw5.xml.jaxb.User;

//@Consumes({"application/xml", "application/json"})
@Path("/kml-api")
@Produces(MediaType.TEXT_PLAIN)
public class KmlApi
{

	private DbHandler db = new DbHandlerImp();

	public KmlApi()
	{
	}

	@GET
	@Path("/message/posts/{lat}/{lng}/{radius}")
	public String getMessages(@Context HttpServletRequest req, @Context HttpServletResponse res,
		@PathParam("lat") String lat, @PathParam("lng") String lng, @PathParam("radius") String radius)
	{
		return getMessages(req, res, "cs236369/hw5/xml/crowd-sourcing-posts.xsl", lat, lng, radius);
	}

	@GET
	@Path("/message/events/{lat}/{lng}/{radius}")
	public String getEvents(@Context HttpServletRequest req, @Context HttpServletResponse res,
		@PathParam("lat") String lat, @PathParam("lng") String lng, @PathParam("radius") String radius)
	{
		return getMessages(req, res, "cs236369/hw5/xml/crowd-sourcing-events.xsl", lat, lng, radius);
	}

	@GET
	@Path("/message/path/{lat}/{lng}/{radius}")
	public String getPath(@Context HttpServletRequest req, @Context HttpServletResponse res,
		@PathParam("lat") String lat, @PathParam("lng") String lng, @PathParam("radius") String radius)
	{
		return getMessages(req, res, "cs236369/hw5/xml/crowd-sourcing-path.xsl", lat, lng, radius);
	}

	private String getMessages(HttpServletRequest req, HttpServletResponse res, String kmlPath, String lat, String lng,
	    String radius)
	{
		Logger logger = Logger.getLogger(getClass());
		try
		{
			double x = Double.parseDouble(lat);
			double y = Double.parseDouble(lng);
			double d = Double.parseDouble(radius);

			Point p = new GeometryFactory().createPoint(new Coordinate(x, y));

			Collection<DbMessage> msg = db.find(x,y, d);
			CrowdSourcing cs = new CrowdSourcing();
			for (DbMessage m : msg)
			{

				Message mb = new Message();
				mb.setContent(m.getContent());
				
				GregorianCalendar c1 = new GregorianCalendar();
				c1.setTime(m.getDate());
				XMLGregorianCalendar dateMsg = DatatypeFactory.newInstance().newXMLGregorianCalendar(c1);
				mb.setDate(dateMsg);
				
				if (m.getType() == DbMsgType.event)
				{
					DbEvent dbev= m.getEvents().get(0);
					Event event = new Event();
					event.setCapacity(BigInteger.valueOf(dbev.getCapacity().intValue()));
					GregorianCalendar c = new GregorianCalendar();
					c.setTime(m.getDate());
					XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
					event.setDate(date2);
					event.setId(BigInteger.valueOf(dbev.getId().longValue()));
					event.setRegistered(BigInteger.valueOf(dbev.getRegistered().longValue()));
					//TODO add if the user is registered or not...
					mb.setEvent(event);
					
				}
				
				Location l = new Location();
				
				l.setLatitude(m.getX());
				l.setLongtitude(m.getY());
				mb.setLocation(l);

				mb.setType(MessageType.fromValue(m.getType().toString()));
				
				User user = new User();
				user.setUsername(m.getUser().getUsername());
				user.setSirName(m.getUser().getSirName());
				user.setLastName(m.getUser().getLastName());
				mb.setUser(user );
				
				cs.getMessage().add(mb);

			}
			XmlUtils xmlUtils = new XmlUtils();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			xmlUtils.writeToOutputStream(cs, bos);
			InputStream xml = new ByteArrayInputStream(bos.toByteArray());
			InputStream xsl = ResourceLoader.getResourceAsStream(kmlPath);
			ByteArrayOutputStream kml = new ByteArrayOutputStream();
			xmlUtils.convertInputStreamUsingXsl(xml, xsl, kml);
			return new String(kml.toByteArray());
		}
		catch (Exception e)
		{
			logger.error("", e);
			return new String("");
		}
	}

}
